package org.openkoala.koala.toolbar;

import java.io.File;
import java.lang.reflect.InvocationTargetException;

import org.dom4j.Document;
import org.dom4j.Element;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.commands.IHandlerListener;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.debug.ui.RefreshTab;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.internal.ui.packageview.PackageFragmentRootContainer;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.m2e.actions.MavenLaunchConstants;
import org.eclipse.m2e.internal.launch.Messages;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.ISelectionService;
import org.eclipse.ui.internal.Workbench;
import org.openkoala.koala.action.xml.DocumentUtil;
import org.openkoala.koala.action.xml.PomXmlReader;
import org.openkoala.koala.action.xml.XPathQueryUtil;
import org.openkoala.koala.console.ConsoleFactory;
import org.openkoala.koala.maven.MavenExcuter;
import org.openkoala.koala.util.ProjectQueryUtil;
import org.openkoala.koala.utils.ModuleLayer;
import org.openkoala.koala.widget.Module;
import org.openkoala.koala.widget.Project;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@SuppressWarnings("restriction")
public class RunProjectHandler implements IHandler {
	
	private static final Logger log = LoggerFactory.getLogger(RunProjectHandler.class);
	private static final String separator = File.separator;
	private Project project;
	private String selectionPath;
	
	@Override
	public Object execute(ExecutionEvent event) throws ExecutionException {
		initProject();
		if (project == null) {
			return null;
		}
		
		ConsoleFactory.showConsole();
		String projectPath = project.getPath() + separator + project.getAppName();
		installProject(projectPath);
		
		String webModulePath = getWebModulePath(projectPath);
		launch(webModulePath);
		
		return null;
	}
	
	private void installProject(final String projectPath) {
		ProgressMonitorDialog monitorDialog = new ProgressMonitorDialog(getShell());
		monitorDialog.setOpenOnRun(false);
		
		try {
			monitorDialog.run(true, true, new IRunnableWithProgress() {
			    
				@Override
				public void run(IProgressMonitor monitor) throws InvocationTargetException,
						InterruptedException {
				    
					monitor.beginTask("构建项目...", 2);
					monitor.worked(1);
					
					MavenExcuter.run(projectPath, "install");
					
					monitor.worked(2);
					monitor.done();
				}
			});
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	private void launch(String webModulePath) {
		ILaunchConfiguration configuration = createLaunchConfiguration(webModulePath, "jetty:run -DskipTests=true");
		if (configuration == null) {
			return;
		}
		DebugUITools.launch(configuration, "run");
	}
	
	private void initProject() {
		initSelectionPath();
		if (selectionPath != null) {
			project = ProjectQueryUtil.getProject(selectionPath);
		}
	}
	
	private void initSelectionPath() {
		ISelectionService selectionService =     
	            Workbench.getInstance().getActiveWorkbenchWindow().getSelectionService();    
		ISelection selection = selectionService.getSelection();    
    
		if(!(selection instanceof IStructuredSelection)) {
			popupErrorMessage("请选择项目！");
		}
		
        IProject project = null;
    	IStructuredSelection iStructuredSelection = (IStructuredSelection) selection;
        Object element = iStructuredSelection.getFirstElement();    

        if (element instanceof IResource) {    
            project= ((IResource)element).getProject();    
        } else if (element instanceof PackageFragmentRootContainer) {    
            IJavaProject jProject =     
                ((PackageFragmentRootContainer)element).getJavaProject();    
            project = jProject.getProject();    
        } else if (element instanceof IJavaElement) {    
            IJavaProject jProject= ((IJavaElement)element).getJavaProject();    
            project = jProject.getProject();    
        }
        
        if (project != null) {
        	selectionPath = project.getLocationURI().getPath();
        }
	}
	
	private String getWebModulePath(String projectPath) {
		String result = null;
		if(selectionIsWebModule()) {
			result = selectionPath;
		}
		
		for (Module module : project.getModule()) {
			if (module.getModuleType().equals(ModuleLayer.war.name())) {
				result = projectPath + separator + module.getModuleName();
			}
		}
		return result;
	}
	
	private boolean selectionIsWebModule() {
		String theSelectionPath = selectionPath;
		theSelectionPath = theSelectionPath.replaceAll("\\\\", "/");
		if (theSelectionPath.endsWith("/")) {
			theSelectionPath = theSelectionPath.substring(0,-1);
		}
		String projectPom = theSelectionPath + "/pom.xml";
		Document document = DocumentUtil.readDocument(projectPom);
		Element element = XPathQueryUtil.querySingle(PomXmlReader.POM_XMLS, "/xmlns:project/xmlns:packaging", document);
		return element.getData().equals(ModuleLayer.war.name());
	}

	/**
	 * 弹出框提示出错信息
	 * @param errorMessage
	 */
	private void popupErrorMessage(String errorMessage) {
		MessageBox messageBox = new MessageBox(getShell(), SWT.ICON_ERROR);
		messageBox.setMessage(errorMessage);
		messageBox.open();
	}

	private Shell getShell() {
		return Workbench.getInstance().getActiveWorkbenchWindow().getShell();
	}

	@Override
	public void addHandlerListener(IHandlerListener handlerListener) {
	}

	@Override
	public void dispose() {
	}

	@Override
	public boolean isEnabled() {
		return true;
	}

	@Override
	public boolean isHandled() {
		return true;
	}

	@Override
	public void removeHandlerListener(IHandlerListener handlerListener) {
	}

	private ILaunchConfiguration createLaunchConfiguration(String path, String goal) {
		try {
			ILaunchManager launchManager = DebugPlugin.getDefault()
					.getLaunchManager();
			ILaunchConfigurationType launchConfigurationType = launchManager
					.getLaunchConfigurationType(MavenLaunchConstants.LAUNCH_CONFIGURATION_TYPE_ID);

			String launchSafeGoalName = goal.replace(':', '-');

			ILaunchConfigurationWorkingCopy workingCopy = launchConfigurationType
					.newInstance(
							null, //
							NLS.bind(Messages.ExecutePomAction_executing,
									launchSafeGoalName, path.replace(separator, "-")));
			workingCopy.setAttribute(MavenLaunchConstants.ATTR_POM_DIR, path);
			workingCopy.setAttribute(MavenLaunchConstants.ATTR_GOALS, goal);
			workingCopy.setAttribute(IDebugUIConstants.ATTR_PRIVATE, true);
			workingCopy.setAttribute(RefreshTab.ATTR_REFRESH_SCOPE,
					"${project}"); //$NON-NLS-1$
			workingCopy.setAttribute(RefreshTab.ATTR_REFRESH_RECURSIVE, true);

			return workingCopy;
		} catch (CoreException ex) {
			log.error(ex.getMessage(), ex);
		}
		return null;
	}

}
